//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

//
// HiKeyLockPanel.cpp
//

#include "HiKeyLockPanel.h"

#define MAX_LOADSTRING 100
#define WINDOWS_NAME       (L"KeyLock")
#define WINDOWS_CLASS_NAME WINDOWS_NAME
#define REG_NAME           WINDOWS_NAME

int g_iApplet = 0; 
BOOL CreatePropertySheet(HWND hWnd, int iApplet);

#define OUTPUT_MSG(cond,printf_exp)     (NKDbgPrintfW printf_exp)

////////////////////////////////////////////////////////
//    DllMain
//
////////////////////////////////////////////////////////
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    if (DLL_PROCESS_ATTACH == ul_reason_for_call)
    {
        g_hInstance = (HINSTANCE)hModule;
    }

    return TRUE;
}


////////////////////////////////////////////////////////
//    Do initialization, eg memory allocations, etc.
//  return TRUE if all OK and FALSE if applet shouldn't
//  be loaded
//
////////////////////////////////////////////////////////
BOOL InitApplet(HWND hwndParent)
{
    return TRUE;
}


////////////////////////////////////////////////////////
//    Do cleanup here
//  
////////////////////////////////////////////////////////
void TermApplet()
{
    return;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_CREATE:
            SHINITDLGINFO shidi;
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLG;
            shidi.hDlg = hWnd;
            SHInitDialog(&shidi);

            (void)CreatePropertySheet(hWnd, g_iApplet);            
            break;

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
   }

   return 0;
}
BOOL LoadDialog(HINSTANCE hInstance, HWND hWndParent)
{
    HWND    hWnd = NULL;
    TCHAR   szTitle[MAX_LOADSTRING];            // The title bar text

    LoadString(hInstance, APPLET_DESC, szTitle, MAX_LOADSTRING);

    hWnd = FindWindow(WINDOWS_NAME, szTitle);
    if (hWnd)
    {
        OUTPUT_MSG(TRUE, (TEXT("****HAS RUNNING*******!\r\n")));
        SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));
        return 0;
    }
    WNDCLASS    wc;

    wc.style            = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc      = (WNDPROC) WndProc;
    wc.cbClsExtra       = 0;
    wc.cbWndExtra       = 0;
    wc.hInstance        = hInstance;
    wc.hIcon            = NULL;
    wc.hCursor          = 0;
    wc.hbrBackground    = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName     = 0;
    wc.lpszClassName    = WINDOWS_CLASS_NAME;
    
    if (RegisterClass(&wc) != 0)
    {
        hWnd = CreateWindow(WINDOWS_NAME, szTitle, WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT, hWndParent, NULL, hInstance, NULL);
        if (!hWnd)
        {
            UnregisterClass(WINDOWS_CLASS_NAME, hInstance);
            return FALSE;
        }

        DestroyWindow(hWnd);
        UnregisterClass(WINDOWS_CLASS_NAME, hInstance);
        return TRUE;
    }
    else
    {
        OUTPUT_MSG(TRUE, (TEXT("ERROR: HiKeyLockPanel, RegisterClass Fail!\r\n")));
    }

    return FALSE;
}

////////////////////////////////////////////////////////
//    This is the entry point called by ctlpnl.exe
//  
////////////////////////////////////////////////////////
extern "C"
__declspec(dllexport)
LONG WINAPI CPlApplet(HWND hwndCPL, UINT uMsg, LONG lParam1, LONG lParam2)
{
    static int        iInitCount = 0;
    int               iApplet;


    switch (uMsg)
    {
        // First message sent. It is sent only once to
        // allow the dll to initialize it's applet(s)
        case CPL_INIT:
            if (!iInitCount)
            {
                if (!InitApplet(hwndCPL))
                {
                    return FALSE;
                }
            }
            iInitCount++;
            return TRUE;
            
        // Second message sent. Return the count of applets supported
        // by this dll
        case CPL_GETCOUNT:
            // Return the number of applets we support
            return (LONG)((sizeof(SystemApplets))/(sizeof(SystemApplets[0])));

        // Third message sent. Sent once for each applet supported by this dll.
        // The lParam1 contains the number that indicates which applet this is
        // for, from 0 to 1 less than the count of applets.
        // lParam2 is a NEWCPLINFO that should be filled with information about
        // this applet before returning
        case CPL_NEWINQUIRE:
            {
                LPNEWCPLINFO    lpNewCPlInfo;

                lpNewCPlInfo                   = (LPNEWCPLINFO)lParam2;
                iApplet                        = (int)lParam1;
                lpNewCPlInfo->dwSize           = (DWORD)sizeof(NEWCPLINFO);
                lpNewCPlInfo->dwFlags          = 0;
                lpNewCPlInfo->dwHelpContext    = 0;
                lpNewCPlInfo->lData            = SystemApplets[iApplet].icon;
                lpNewCPlInfo->hIcon            = LoadIcon(g_hInstance,(LPCTSTR)MAKEINTRESOURCE(SystemApplets[iApplet].icon));
                lpNewCPlInfo->szHelpFile[0]    = '\0';

                (void)LoadString(g_hInstance,SystemApplets[iApplet].namestring,lpNewCPlInfo->szName,32);
                (void)LoadString(g_hInstance,SystemApplets[iApplet].descstring,lpNewCPlInfo->szInfo,64);
            }

            break;

        // This is sent whenever the user clicks an icon in Settings for one of
        // the applets supported by this dll. lParam1 contains the number indicating
        // which applet. Return 0 if applet successfully launched, non-zero otherwise
        case CPL_DBLCLK:
            g_iApplet = (UINT)lParam1;
            LoadDialog(g_hInstance, hwndCPL);
            break;
            
        // Sent once per applet, before CPL_EXIT
        case CPL_STOP:
            break;
            
        // Sent once before the dll is unloaded
        case CPL_EXIT:
        {
            iInitCount--;
            if (!iInitCount)
            {
                TermApplet();
            }
            break;
        }
        case CPL_IDNAME:
        {
            LPWSTR pszName = (LPTSTR)lParam2;
            _tcscpy(pszName, REG_NAME);
            break;
        }
                
        default:
            break;
    }

    return 0;
}

////////////////////////////////////////////////////////
//    Called to retrieve the values corresponding to the
//   stored in the registry. The necessary
//  registry values are described above
//
////////////////////////////////////////////////////////
HRESULT GetFromRegistry(DWORD *pdwValue)
{
    HKEY       hKey;
    DWORD      dwSize;
    DWORD      dwType;
    HRESULT    hRes;

    TCHAR     *szRegistryKey;
    TCHAR     *szRegValue;
    
    if (!pdwValue)
    {
        return ERROR_INVALID_PARAMETER ;
    }    
    
    szRegistryKey    = REGKEY;
    szRegValue       = KEYLOCK;

    hRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,(LPCWSTR)szRegistryKey,0,KEY_ALL_ACCESS,&hKey);/* lint !-e64*/
    if (hRes != ERROR_SUCCESS)
    {
        return hRes;
    }
    
    dwSize = sizeof(DWORD);
    hRes = RegQueryValueExW(hKey,(LPCWSTR)szRegValue,0,&dwType,(LPBYTE)pdwValue,&dwSize);
    if (hRes != ERROR_SUCCESS)
    {
        goto Done;
    }

Done:
    (void)RegCloseKey(hKey);
    return hRes;
}

////////////////////////////////////////////////////////
//    Called to save backlight related values to the
//  registry
//
////////////////////////////////////////////////////////
HRESULT SetToRegistry(DWORD dwValue)
{
    HKEY      hKey;
    DWORD     dwDisp;
    HRESULT   hRes;

    TCHAR    *szRegistryKey;
    TCHAR    *szRegValue;
    
    szRegistryKey = REGKEY;
    szRegValue    = KEYLOCK;
    
    hRes = RegCreateKeyExW(HKEY_LOCAL_MACHINE, (LPCWSTR)szRegistryKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp);
    if (hRes != ERROR_SUCCESS)
    {
        return hRes;
    }
  
    hRes = RegSetValueExW(hKey,(LPCWSTR)szRegValue,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));

    (void)RegCloseKey(hKey);                    
    
    return hRes;
}



////////////////////////////////////////////////////////
//    The DialogProc for key lock page
//
////////////////////////////////////////////////////////
int CALLBACK KeyLockPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    LPPROPSHEETPAGE ppsp;
    DWORD    dwValue = 0;
    int      i;

    TCHAR   szText[MAXLENGTH + 1];

    switch (uMsg)
    {
        case WM_INITDIALOG:  
        {
            (void)LoadString(g_hInstance, IDS_CAPTION, szText,sizeof(szText)/sizeof(szText[0]));
            SetWindowText(GetDlgItem(hwndDlg,IDC_STATIC1), szText);

            (void)LoadString(g_hInstance, IDS_LOCK_EXCEPT_SUSPEND, szText,sizeof(szText)/sizeof(szText[0]));
            SetWindowText(GetDlgItem(hwndDlg,IDC_RADIO1), szText);

            (void)LoadString(g_hInstance, IDS_LOCK_WHEN_LOCKED, szText,sizeof(szText)/sizeof(szText[0]));
            SetWindowText(GetDlgItem(hwndDlg,IDC_RADIO2), szText);

            (void)LoadString(g_hInstance, IDS_UNLOCKED, szText,sizeof(szText)/sizeof(szText[0]));
            SetWindowText(GetDlgItem(hwndDlg,IDC_RADIO3), szText);
            
            // get current slection
            (void)GetFromRegistry(&dwValue);

            if(!((dwValue == 0) || (dwValue == 1) || (dwValue == 2)))
            {
                dwValue = 0;
            }

            for(i = 0; i < 3; i++)
            {
                if(dwValue == i)
                {
                    (void)SendMessage(GetDlgItem(hwndDlg,(IDC_RADIO1 + i)),BM_SETCHECK,BST_CHECKED,0);
                }
                else
                {
                    (void)SendMessage(GetDlgItem(hwndDlg,(IDC_RADIO1 + i)),BM_SETCHECK,BST_UNCHECKED,0);
                }
            }

            // lParam contains the PROPSHEETPAGE struct; store the HWND into the dword at the end of the struct
            ppsp = (LPPROPSHEETPAGE)lParam;
            *((HWND*)(ppsp + 1)) = hwndDlg;
            
            SHMENUBARINFO shmbi;
            shmbi.cbSize = sizeof(shmbi);
            shmbi.hwndParent = hwndDlg;
            shmbi.dwFlags = SHCMBF_EMPTYBAR;
            SHCreateMenuBar(&shmbi);

            return TRUE;
        }

        case WM_SIZE: 
        {

            if (lParam)
            {
                /* If window is being sized to a non zero value...
                 * invalidate it's client area.
                 */
                InvalidateRect(hwndDlg, NULL, TRUE);
            }
            break;
        }
            
        default:
            break;
    }

    return FALSE;
}


////////////////////////////////////////////////////////
//    This callback is called when each property page gets
//  created and when it gets released.
////////////////////////////////////////////////////////
UINT CALLBACK PropSheetPageProc(HWND hwnd,UINT uMsg,LPPROPSHEETPAGE ppsp)
{
    HWND    hwndDlg;
    HWND    hwndRadio1;
    HWND    hwndRadio2;
    HWND    hwndRadio3;
    DWORD   dwRadiochecked=0;


    // Get the HWND of this property page that was tucked at the
    // end of the propsheetpage struct in the WM_INITDIALOG for this page
    hwndDlg = *((HWND*)(ppsp + 1));

    switch(uMsg) 
    {
        case PSPCB_CREATE:
            //Return any non zero value to indicate success
            return 1;

        case PSPCB_RELEASE:
            //Make this a code block so declaration of iPage is local
            {
                hwndRadio1 = GetDlgItem(hwndDlg,IDC_RADIO1);
                hwndRadio2 = GetDlgItem(hwndDlg,IDC_RADIO2);
                hwndRadio3 = GetDlgItem(hwndDlg,IDC_RADIO3);
                
                if (BST_CHECKED == SendMessage(hwndRadio1,BM_GETCHECK,0,0))
                {
                    dwRadiochecked = 0;
                }
                if (BST_CHECKED == SendMessage(hwndRadio2,BM_GETCHECK,0,0))
                {
                    dwRadiochecked = 1;
                }
                if (BST_CHECKED == SendMessage(hwndRadio3,BM_GETCHECK,0,0))
                {
                    dwRadiochecked = 2;
                }
                
                (void)SetToRegistry(dwRadiochecked);

                // return value is ignored for this message
                return 0;
            }
            
        default:
            // We should never see this case.  If we do we want to know in debug builds.
            //ASSERT(false);
            break;
    }
    //return for default case above
    return (UINT)-1;
}


////////////////////////////////////////////////////////
//    The PropSheetProc for the property sheet.
//
////////////////////////////////////////////////////////
int CALLBACK PropSheetProc(HWND hwndDlg,UINT uMsg,LPARAM lParam)
{
    TCHAR szText[MAXLENGTH + 1];

    switch (uMsg)
    {
        // Returning COMCTL32_VERSION to this message makes the
        // style of the property sheet to be that of the native
        // Pocket PC ones
        case PSCB_GETVERSION:/*lint !e30 */
        {
            return COMCTL32_VERSION;
        }
        
        // The text copied into the lParam on receipt of this message
        // is displayed as the title of the propertysheet
        case PSCB_GETTITLE:/*lint !e30 */
        {
            (void)LoadString( g_hInstance, IDS_TITLE, szText,sizeof(szText)/sizeof(szText[0])); 
            (void)wcsncpy((TCHAR*)lParam, szText, MAXLENGTH);/*lint !e1055*/            
            break;
        }
        
        // The text copied into the lParam on receipt of this message
        // gets displayed as the link text at the bottom of the
        // propertysheet
        //case PSCB_GETLINKTEXT:
        //    wcscpy((TCHAR*)lParam,TEXT("Go to <file:ctlpnl.exe cplmain.cpl,2,2{power}> applet."));
        //    break;
            
        default:
            break;
    }
    
    return 0;
}


////////////////////////////////////////////////////////
//    Called to display this applet as a property sheet
//
////////////////////////////////////////////////////////
BOOL CreatePropertySheet(HWND hwndParent, int iApplet)
{
    BOOL            bReturn = FALSE;
    PROPSHEETHEADER psh;
    PROPSHEETPAGE   ppsp;
    HPROPSHEETPAGE  hpsp[1];
    int             nPages = 1;

    // Set all values for first property page
    ppsp.dwSize      = sizeof(PROPSHEETPAGE)+sizeof(HWND); // Extra space at end of struct to tuck page's hwnd in when it's created
    ppsp.dwFlags     = PSP_DEFAULT|PSP_USECALLBACK;
    ppsp.hInstance   = g_hInstance;
    ppsp.pszTemplate = (LPTSTR)MAKEINTRESOURCE(IDD_PROPPAGE1);
    ppsp.hIcon       = NULL;
    ppsp.pfnDlgProc  = KeyLockPageProc;
    ppsp.lParam      = NULL;
    ppsp.pfnCallback = PropSheetPageProc;
    ppsp.pcRefParent = NULL;

    hpsp[0] = CreatePropertySheetPage(&ppsp);
    if (NULL == hpsp[0]) 
    {
        //Fail out of function
        return bReturn;
    }

    psh.dwSize       = sizeof(psh);
    psh.dwFlags      = PSH_USECALLBACK | PSH_MAXIMIZE;
    psh.hwndParent   = hwndParent;
    psh.hInstance    = g_hInstance;
    psh.pszCaption   = NULL;
    psh.phpage       = hpsp;
    psh.nPages       = nPages;
    psh.nStartPage   = iApplet > (nPages-1)? (nPages-1): iApplet;
    psh.pfnCallback  = PropSheetProc;

    if(PropertySheet(&psh) != -1)
    {
        bReturn = TRUE;
    }
    else 
    {
        OUTPUT_MSG(TRUE, (TEXT("****Create KeyLock Panel ERROR*******!\r\n")));
        //Clean up PropertySheetPages as they weren't used by the PropertySheet
        (void)DestroyPropertySheetPage(hpsp[0]);
    }
    
    return bReturn;
}
